/*
 * IXmlNode.h
 *
 *  Created on: 08.06.2012
 *      Author: caffeine
 */

#ifndef __IXmlNode_H_
#define __IXmlNode_H_

#include <lampe/types.h>
#include <lampe/IReferenceCounted.h>
#include <lampe/xml/IXmlNode.h>
#include <lampe/stream/IReader.h>
#include <lampe/xml/IXmlNode.h>
#include <lampe/xml/IAttribute.h>

//#include "CXMLSaxParser.h"
#include "CXMLSaxList.h"

namespace lampe{
namespace xml{

/**
 * @class IXmlNode
 * Узел XML дерева
 */
class CXmlNode: public IXmlNode {
private:
	LAMPE_VECTOR_VENDOR<IAttribute*> attributes;
	LAMPE_VECTOR_VENDOR<IXmlNode*> nodes;
	String name;
	String path;
	String body;
	bool cdata;

	String current_dir;

	IXmlNode*parent;
	void*tagObject;
	void updatePath();
public:

    /**
	 * Устанавливает объект, принадлежащий данному узлу
	 *
	 * @param arg указатель на объект, который должен пренаджелать узлу
	 * */
	virtual void setTag(void*arg);

    /**
	 * Возвращяет объект, пренадлежащий узлу
	 *
	 * @return указатель на объект пренадлежащий узлу
	 * */
	virtual void*getTag();

    /**
	 * Устанавливает имя узла
	 *
	 * @param arg новое имя узла
	 * */
	virtual void setName(String arg);

	

    /**
	 * Возвращяет имя узла (тэга)
	 *
	 * @return имя узла (тэга)
	 */
	virtual String getName();



	/**
	 * Возвращяет полный путь узла, включая его собственное имя
	 *
	 * @return полный путь тэга. Например root/material/flag
	 */
	virtual String getPath();

	/**
	 * Проверяет входит ли указанный путь в текущий путь.
	 * Например, полный путь /root/material/flag, а дан путь
	 * material/flag. Тогда в этом случае путь войдёт в полный путь
	 *
	 * @param часть пути
	 *
	 * @return если TRUE, то входит. Иначе FALSE
	 */
	virtual bool isPartOfPath(String path);

    /**
	 * Удаляет все атрибуты
	 */
	virtual void clearAttributes();

	/**
	 * Добовляет атрибут в список атрибутов
	 *
	 * @param a атрибут
	 */
	virtual void addAttributeObj(IAttribute*a);

	/**
	 * Добовляет атрибут в список атрибутов
	 *
	 * @param name имя атрибута
	 * @param value значение
	 */
	virtual void addAttribute(String name,String value);

	/**
	 * Удаляет атрибут
	 *
	 * @param index номер атрибута
	 */
	virtual void removeAttribute(u32 index);

	/**
	 * Возвращяет количество атрибутов в данном узле
	 */
	virtual u32 getAttributeCount();

	/**
	 * Возвращяет атрибут по его номеру. Если номер будет привышать
	 * количество атрибутов, то вернётся NULL
	 *
	 * @param index номер атрибута.
	 * @return атрибут
	 */
	virtual IAttribute*getAttribute(u32 index);

	/**
	 * Переносит все атрибуты данного узла на другой указанный узел
	 *
	 * @param node узел, куда нужно переместить все атрибуты
	 */
	virtual void dropAttributesTo(IXmlNode*node);

	/**
	 * Переносит все атрибуты данного узла на уровень верх
	 */
	virtual void dropAttributesUp();

	/**
	 * Возвращяет номер атрибута по его имяни
	 *
	 * @param Name имя атрибуты
	 * @return номер атрибута. Если атрибут с указанным имянем не найдет, то вернёт -1
	 */
	virtual s32 indexOfAttribute(String Name);

	/**
	 * Конструктор
	 *
	 * @param reader устройство чтения XML
	 * @Parent родитеский узел
	 */
	//IXmlNode(CReader*reader,String current_dir,IXmlNode*Parent=0);
	CXmlNode(CXMLSaxList*reader,String current_dir,IXmlNode*Parent=0);
	CXmlNode();

	/**
	 * Устанавливает родительский узел для данного элемента
	 *
	 * @param Parent узел родитель
	 */
	virtual void setParent(IXmlNode*Parent);

	virtual void setParentEx(IXmlNode*Parent,u32 index);

	/**
	 * Возвращяет узел, которому пренадлежит данный узел
	 *
	 * @return узел-ордитель
	 */
	virtual IXmlNode*getParent();

	/**
	 * Возвращяет объект, TAG которого не раверн NULL. Поиск производится вверх
	 *
	 * @param checkThis нужно ли проверять TAG данного узла
	 * @return узел, который содержит не TAG. Если нужный узел не найден, то вернёт NULL
	 */
	virtual IXmlNode*findNodeNotNull(bool checkThis);



	/**
	 * Возвращяет значение атрибута по его имяни
	 *
	 * @param name имя атрибута
	 * @param default значение по умолчанию
	 */
	virtual String getAttString(String name,String deault="");

	/**
	 * Возвращяет значение атрибута по его имяни в виде логического значения
	 *
	 * @param name имя атрибута
	 * @param default значение по умолчанию
	 */
	virtual bool getAttBool(String name,bool deault=false);

	/**
	 * Возвращяет значение атрибута по его имяни в виде не целого
	 *
	 * @param name имя атрибута
	 * @param default значение по умолчанию
	 */
	virtual f32 getAttF32(String name,f32 deault=0);

	/**
	 * Возвращяет значение атрибута по его имяни в виде беззанового целого
	 *
	 * @param name имя атрибута
	 * @param default значение по умолчанию
	 */
	virtual u32 getAttU32(String name,u32 deault=0);

	/**
	 * Возвращяет значение атрибута по его имяни в виде занового целого
	 *
	 * @param name имя атрибута
	 * @param default значение по умолчанию
	 */
	virtual s32 getAttS32(String name,s32 deault=0);
	

	//virtual core::rect<s32> getAttRect2I(String name);
	//virtual core::rect<f32> getAttRect2F(String name);

	virtual Vector2di getAttVec2I(String name,s32 X=0,s32 Y=0);
	virtual Vector2df getAttVec2F(String name,f32 X=0,f32 Y=0);

	virtual Vector3di getAttVec3I(String name,s32 X=0,s32 Y=0,s32 Z=0);
	virtual Vector3df getAttVec3F(String name,f32 X=0,f32 Y=0,f32 Z=0);

	virtual SColor getAttColor(String name,u32 A=0,u32 R=0,u32 G=0,u32 B=0);
	
	//--------------------------------
	
	virtual void setAttString(String name,String value);
	
	virtual void setAttS32(String name,s32 value);
	virtual void setAttBool(String name,bool value);

	//virtual void setAttRect2I(String name,core::rect<s32> value);
	//virtual void setAttRect2F(String name,core::rect<f32> value);

	virtual void setAttVec2I(String name,Vector2di value);
	virtual void setAttVec2F(String name,Vector2df value);

	virtual void setAttVec3I(String name,Vector3di value);
	virtual void setAttVec3F(String name,Vector3df value);

	virtual void setAttColor(String name,SColor value);

	/**
	 * Возвращяет следующий узел, идущий за указанным
	 *
	 * @param arg указанный текущий узел
	 * @return следующий узел
	 */
	virtual IXmlNode*giveNext(IXmlNode*arg);

	/**
	 * Удаляет все дочернии узлы
	 */
	virtual void clearNodes();

	virtual String getCurrentDirectory();

	/**
	 * Добовляет узел
	 *
	 * @param node указатель на узел, который нужно добавить
	 */
	virtual void addNode(IXmlNode*node);


    /**
	 * Добовляет узел на определённую позицию
	 *
	 * @param node узел, который нужно добавить
	 * @param index индекс, в который нужно вставить узел
	 */
	virtual void insertNode(IXmlNode*node,u32 index);

	/**
	 * Удаляет узел по его номеру
	 *
	 * @param index номер узла, который нужно удалить
	 */
	virtual void removeNodeByIndex(u32 index);

	/**
	 * Удаляет узел по его указателю
	 *
	 * @param node указатель на узел, который нужно удалить
	 * @exception NullException
	 */
	virtual void removeNode(IXmlNode*node);

	/**
	 * Ищет узлы с указанным имянем и возвращяет их в виде списка
	 *
	 * @param Name имя узла, который нужно искать
	 * @param res указатель на лист, куда нужно помещать результат
	 * @param R если TRUE, то поиск видётся во всех дочерних узлах, если FALSE, то только в том, который его вызвал
	 */
	virtual void getNodes(String Name,LAMPE_VECTOR_VENDOR<IXmlNode*>*res,bool R=false);

	/**
	 * * Ищет узлы с указанным имянем и возвращяет их в виде списка
	 *
	 * @param name имя узла, который нужно искать
	 * @param R если TRUE, то поиск видётся во всех дочерних узлах, если FALSE, то только в том, который его вызвал
	 * @return список узлов
	 */
	virtual LAMPE_VECTOR_VENDOR<IXmlNode*>getNodes(String Name,bool R=false);

	/**
	 * Возвращяет номер узла по его указателю
	 *
	 * @param node указатель на узел
	 * @return номер узла. Если узел не найден, то вернёт -1
	 */
	virtual s32 indexOf(IXmlNode*node);

	/**
	 * Возвращяет дочерний узел по его номеру
	 *
	 * @param index номер узла
	 * @return узел. Если номер узла привышает количество узлов, то вернёт NULL
	 */
	virtual IXmlNode*getNode(u32 index);

	/***
	 * Заменяет значение списка внутриних узлов на указанный.
	 *
	 * @return index номер, куда нужно вставить узел
	 * @return node узел, которым нужно заменить узел
	 */
	virtual void setNode(u32 index,IXmlNode*node);

	/**
	 * Возвращяет количество дочерних узлов
	 *
	 * @return количество узлов
	 */
	virtual u32 getNodeCount();

	/**
	 * Вернёт тело текущего узла и всех его дочерних элементов
	 * в виде XML текста
	 *
	 * @param level уровень отступа
	 * @return итоговый XML текст
	 */
	virtual String toXML(u32 level=0);

	/**
	 * Перенесёт все дочернии узлы на уровень верх
	 */
	virtual void dropChildUp();

	/**
	 * Перенесёт все дочернии узлы в указанный узел
	 *
	 * @param node узел, в который необходимо перенести все дочернии элементы
	 */
	virtual void dropChildTo(IXmlNode*node);

	virtual void dropChildToEx(IXmlNode*node,u32 index);

    virtual void serialization(lampe::stream::IWriter*stream);
    virtual void deserialization(lampe::stream::IReader*stream);

	/**
	 * Диструктор. Уничтожит все атрибуты и дочернии узлы
	 */
	virtual ~CXmlNode();
};

u32 getNodeCount();

}//namespace xml
}//namespace lampe

#endif /* IXmlNode_H_ */
